package com.college.common.utils.object;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace;

/**
 * @author 小C工作室
 */
@Slf4j
public class ObjectUtil {

	private ObjectUtil() {
	}

	/**
	 * 判断对象是否为空，如果为空则创建按一个对象返回，否则直接返回
	 *
	 * @param object
	 * @param tClass
	 * @param <T>
	 * @return
	 */
	public static <T> T filterObjectNull(T object, Class<? extends T> tClass) {
		if (isEmpty(object)) {
			try {
				object = tClass.newInstance();
			} catch (InstantiationException | IllegalAccessException e) {
				log.error(getStackTrace(e));
				e.printStackTrace();
			}
		}
		return object;
	}


	/**
	 * 对象属性复制类型转换
	 *
	 * @param source      源对象
	 * @param targetClass 目标类型
	 * @param <T>
	 * @param <H>
	 * @return
	 */
	public static <T, H> H objectCopyProperties(T source, Class<H> targetClass) {
		H h = null;
		try {
			h = targetClass.newInstance();
			BeanUtils.copyProperties(source, h);
		} catch (InstantiationException | IllegalAccessException e) {
			log.error(getStackTrace(e));
			e.printStackTrace();
		}
		return h;
	}

	/**
	 * 对象空判断
	 *
	 * @param obj
	 * @return
	 */
	public static boolean isEmpty(Object obj) {
		if (obj == null) {
			return true;
		}
		if (obj.getClass().isArray()) {
			return Array.getLength(obj) == 0;
		}
		if (obj instanceof CharSequence) {
			return ((CharSequence) obj).length() == 0;
		}
		if (obj instanceof Collection) {
			return ((Collection<?>) obj).isEmpty();
		}
		if (obj instanceof Map) {
			return ((Map<?, ?>) obj).isEmpty();
		}
		// else
		return false;
	}

	public static boolean isNotEmpty(Object obj) {
		return !isEmpty(obj);
	}

	/**
	 * @param sourceBean 被提取的对象bean
	 * @param targetBean 用于合并的对象bean
	 * @return targetBean 合并后的对象
	 * @Description: 该方法是用于相同对象不同属性值的合并，如果两个相同对象中同一属性都有值，
	 * 		那么sourceBean中的值会覆盖tagetBean重点的值
	 * @return: Object
	 */
	public static <T> T combineObject(T sourceBean, T targetBean) {
		if (targetBean == null) {
			return sourceBean;
		}
		Class sourceBeanClass = sourceBean.getClass();
		Class targetBeanClass = targetBean.getClass();
		Field[] sourceFields = sourceBeanClass.getDeclaredFields();
		Field[] targetFields = targetBeanClass.getDeclaredFields();
		for (int i = 0; i < sourceFields.length; i++) {
			Field sourceField = sourceFields[i];
			Field targetField = targetFields[i];
			sourceField.setAccessible(true);
			targetField.setAccessible(true);
			try {
				if (Boolean.FALSE.equals(sourceField.get(sourceBean) == null)) {
					targetField.set(targetBean, sourceField.get(sourceBean));
				}
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return targetBean;
	}


		/**
		 * 判断对象属性是否全部有值（string／Integer/List类型）
		 * @param object
		 * @return
		 */
		public static boolean objCheckIsNull(Object object){
			Class clazz = (Class)object.getClass(); // 得到类对象
			Field fields[] = clazz.getDeclaredFields(); // 得到所有属性
			boolean flag = true; //定义返回结果，默认为true
			for(Field field : fields){
				field.setAccessible(true);
				Object fieldValue = null;
				Type fieldType=null;
				String fieldName=null;
				try {
					fieldValue = field.get(object); //得到属性值
					fieldType =field.getType();//得到属性类型
					fieldName = field.getName(); // 得到属性名
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				if(fieldValue == null){  //只要有一个属性值为null 就返回false 表示对象属性有为null的
					flag = false;
					break;
				}
				if(fieldType.equals(Integer.class)&& (Integer)fieldValue == 0 ){
					flag = false; //Integer默认属性值为0
					break;
				}
				if(List.class.isAssignableFrom((Class<?>) fieldType)){
					try {
						Class<?> clzz = fieldValue.getClass();
						//反射调用获取到list的size方法来获取到集合的大小
						Method sizeMethod = clzz.getDeclaredMethod("size");
						//集合长度
						int size = (int) sizeMethod.invoke(fieldValue);
						if (size < 1) {
							flag = false; //list中条数为0
							break;
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			return flag;
		}


}
